﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using HslCommunication.LogNet;
using Newtonsoft.Json.Linq;

namespace HslCommunication.Core
{
	/// <summary>
	/// 文件集容器，绑定一个文件夹的文件信息组，提供了文件夹的文件信息的获取，更新接口<br />
	/// File set container, which binds the file information group of a folder, provides the file information acquisition and update interface of the folder
	/// </summary>
	// Token: 0x02000131 RID: 305
	public class GroupFileContainer
	{
		/// <summary>
		/// 实例化一个新的指定目录的文件管理容器<br />
		/// Instantiates a new file management container for the specified directory
		/// </summary>
		/// <param name="logNet">日志记录对象，可以为空</param>
		/// <param name="path">文件的路径</param>
		// Token: 0x060019A4 RID: 6564 RVA: 0x000806CC File Offset: 0x0007E8CC
		public GroupFileContainer(ILogNet logNet, string path)
		{
			this.LogNet = logNet;
			this.dirPath = path;
			bool flag = !string.IsNullOrEmpty(path);
			if (flag)
			{
				this.LoadByPath(path);
			}
		}

		/// <summary>
		/// 包含所有文件列表信息的json文本缓存<br />
		/// JSON text cache containing all file list information
		/// </summary>
		// Token: 0x17000554 RID: 1364
		// (get) Token: 0x060019A5 RID: 6565 RVA: 0x0008072C File Offset: 0x0007E92C
		public string JsonArrayContent
		{
			get
			{
				return this.jsonArrayContent;
			}
		}

		/// <summary>
		/// 获取文件的数量<br />
		/// Get the number of files
		/// </summary>
		// Token: 0x17000555 RID: 1365
		// (get) Token: 0x060019A6 RID: 6566 RVA: 0x00080734 File Offset: 0x0007E934
		public int FileCount
		{
			get
			{
				return this.filesCount;
			}
		}

		/// <summary>
		/// 当前的目录信息
		/// </summary>
		// Token: 0x17000556 RID: 1366
		// (get) Token: 0x060019A7 RID: 6567 RVA: 0x0008073C File Offset: 0x0007E93C
		public string DirectoryPath
		{
			get
			{
				return this.dirPath;
			}
		}

		/// <summary>
		/// 当文件数量发生变化的时候触发的事件<br />
		/// Event triggered when the number of files changes
		/// </summary>
		// Token: 0x14000039 RID: 57
		// (add) Token: 0x060019A8 RID: 6568 RVA: 0x00080744 File Offset: 0x0007E944
		// (remove) Token: 0x060019A9 RID: 6569 RVA: 0x0008077C File Offset: 0x0007E97C
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public event GroupFileContainer.FileCountChangedDelegate FileCountChanged;

		/// <summary>
		/// 下载文件时调用，根据当前的文件名称，例如 123.txt 获取到在文件服务器里映射的文件名称，例如返回 b35a11ec533147ca80c7f7d1713f015b7909<br />
		/// Called when downloading a file. Get the file name mapped in the file server according to the current file name, such as 123.txt. 
		/// For example, return b35a11ec533147ca80c7f7d1713f015b7909.
		/// </summary>
		/// <param name="fileName">文件的实际名称</param>
		/// <returns>文件名映射过去的实际的文件名字</returns>
		// Token: 0x060019AA RID: 6570 RVA: 0x000807B4 File Offset: 0x0007E9B4
		public string GetCurrentFileMappingName(string fileName)
		{
			string result = string.Empty;
			object obj = this.hybirdLock;
			lock (obj)
			{
				for (int i = 0; i < this.groupFileItems.Count; i++)
				{
					bool flag2 = this.groupFileItems[i].FileName == fileName;
					if (flag2)
					{
						result = this.groupFileItems[i].MappingName;
						GroupFileItem groupFileItem = this.groupFileItems[i];
						long downloadTimes = groupFileItem.DownloadTimes;
						groupFileItem.DownloadTimes = downloadTimes + 1L;
					}
				}
			}
			this.coordinatorCacheJsonArray.StartOperaterInfomation();
			return result;
		}

		/// <summary>
		/// 上传文件时掉用，通过比对现有的文件列表，如果没有，就重新创建列表信息<br />
		/// Used when uploading files, by comparing existing file lists, if not, re-creating list information
		/// </summary>
		/// <param name="fileName">文件名，带后缀，不带任何的路径</param>
		/// <param name="fileSize">文件的大小</param>
		/// <param name="mappingName">文件映射名称</param>
		/// <param name="owner">文件的拥有者</param>
		/// <param name="description">文件的额外描述</param>
		/// <returns>映射的文件名称</returns>
		// Token: 0x060019AB RID: 6571 RVA: 0x0008087C File Offset: 0x0007EA7C
		public string UpdateFileMappingName(string fileName, long fileSize, string mappingName, string owner, string description)
		{
			string text = string.Empty;
			object obj = this.hybirdLock;
			lock (obj)
			{
				for (int i = 0; i < this.groupFileItems.Count; i++)
				{
					bool flag2 = this.groupFileItems[i].FileName == fileName;
					if (flag2)
					{
						text = this.groupFileItems[i].MappingName;
						this.groupFileItems[i].MappingName = mappingName;
						this.groupFileItems[i].Description = description;
						this.groupFileItems[i].FileSize = fileSize;
						this.groupFileItems[i].Owner = owner;
						this.groupFileItems[i].UploadTime = DateTime.Now;
						break;
					}
				}
				bool flag3 = string.IsNullOrEmpty(text);
				if (flag3)
				{
					this.groupFileItems.Add(new GroupFileItem
					{
						FileName = fileName,
						FileSize = fileSize,
						DownloadTimes = 0L,
						Description = description,
						Owner = owner,
						MappingName = mappingName,
						UploadTime = DateTime.Now
					});
				}
			}
			this.coordinatorCacheJsonArray.StartOperaterInfomation();
			return text;
		}

		/// <summary>
		/// 删除一个文件信息，传入文件实际的名称，例如 123.txt 返回被删除的文件的guid名称，例如返回 b35a11ec533147ca80c7f7d1713f015b7909   此方法存在同名文件删除的风险<br />
		/// Delete a file information. Pass in the actual name of the file. For example, 123.txt returns the guid name of the deleted file. For example, it returns b35a11ec533147ca80c7f7d1713f015b7909. There is a risk of deleting the file with the same name
		/// </summary>
		/// <param name="fileName">实际的文件名称，如果 123.txt</param>
		/// <returns>映射之后的文件名，例如 b35a11ec533147ca80c7f7d1713f015b7909</returns>
		// Token: 0x060019AC RID: 6572 RVA: 0x000809FC File Offset: 0x0007EBFC
		public string DeleteFile(string fileName)
		{
			string result = string.Empty;
			object obj = this.hybirdLock;
			lock (obj)
			{
				for (int i = 0; i < this.groupFileItems.Count; i++)
				{
					bool flag2 = this.groupFileItems[i].FileName == fileName;
					if (flag2)
					{
						result = this.groupFileItems[i].MappingName;
						this.groupFileItems.RemoveAt(i);
						break;
					}
				}
			}
			this.coordinatorCacheJsonArray.StartOperaterInfomation();
			return result;
		}

		/// <summary>
		/// 判断当前的文件名是否在文件的列表里，传入文件实际的名称，例如 123.txt，如果文件存在，返回 true, 如果不存在，返回 false<br />
		/// Determine whether the current file name is in the file list, and pass in the actual file name, such as 123.txt, 
		/// if it exists, return true, if it does not exist, return false
		/// </summary>
		/// <param name="fileName">实际的文件名称，如果 123.txt</param>
		/// <returns>如果文件存在，返回 true, 如果不存在，返回 false</returns>
		// Token: 0x060019AD RID: 6573 RVA: 0x00080AB4 File Offset: 0x0007ECB4
		public bool FileExists(string fileName)
		{
			bool result = false;
			object obj = this.hybirdLock;
			lock (obj)
			{
				for (int i = 0; i < this.groupFileItems.Count; i++)
				{
					bool flag2 = this.groupFileItems[i].FileName == fileName;
					if (flag2)
					{
						result = true;
						bool flag3 = !File.Exists(Path.Combine(this.dirPath, this.groupFileItems[i].MappingName));
						if (flag3)
						{
							result = false;
							ILogNet logNet = this.LogNet;
							if (logNet != null)
							{
								logNet.WriteError("File Check exist failed, find file in list, but mapping file not found");
							}
						}
						break;
					}
				}
			}
			return result;
		}

		/// <summary>
		/// 删除一个文件信息，传入文件唯一的guid的名称，例如 b35a11ec533147ca80c7f7d1713f015b7909 返回被删除的文件的guid名称<br />
		/// Delete a file information, pass in the unique GUID name of the file, for example b35a11ec533147ca80c7f7d1713f015b7909 return the GUID name of the deleted file
		/// </summary>
		/// <param name="guidName">实际的文件名称，如果 b35a11ec533147ca80c7f7d1713f015b7909</param>
		/// <returns>映射之后的文件名，例如 b35a11ec533147ca80c7f7d1713f015b7909</returns>
		// Token: 0x060019AE RID: 6574 RVA: 0x00080B84 File Offset: 0x0007ED84
		public string DeleteFileByGuid(string guidName)
		{
			string result = string.Empty;
			object obj = this.hybirdLock;
			lock (obj)
			{
				for (int i = 0; i < this.groupFileItems.Count; i++)
				{
					bool flag2 = this.groupFileItems[i].MappingName == guidName;
					if (flag2)
					{
						result = this.groupFileItems[i].MappingName;
						this.groupFileItems.RemoveAt(i);
						break;
					}
				}
			}
			this.coordinatorCacheJsonArray.StartOperaterInfomation();
			return result;
		}

		/// <summary>
		/// 删除当前目录下所有的文件信息，返回等待被删除的文件列表，是映射文件名：b35a11ec533147ca80c7f7d1713f015b7909
		/// </summary>
		/// <returns>映射之后的文件列表，例如 b35a11ec533147ca80c7f7d1713f015b7909</returns>
		// Token: 0x060019AF RID: 6575 RVA: 0x00080C3C File Offset: 0x0007EE3C
		public List<string> ClearAllFiles()
		{
			List<string> list = new List<string>();
			object obj = this.hybirdLock;
			lock (obj)
			{
				for (int i = 0; i < this.groupFileItems.Count; i++)
				{
					list.Add(this.groupFileItems[i].MappingName);
				}
				this.groupFileItems.Clear();
			}
			this.coordinatorCacheJsonArray.StartOperaterInfomation();
			return list;
		}

		/// <summary>
		/// 缓存JSON文本的方法，该机制使用乐观并发模型完成<br />
		/// Method for caching JSON text, which is done using an optimistic concurrency model
		/// </summary>
		// Token: 0x060019B0 RID: 6576 RVA: 0x00080CD8 File Offset: 0x0007EED8
		private void CacheJsonArrayContent()
		{
			object obj = this.hybirdLock;
			lock (obj)
			{
				this.filesCount = this.groupFileItems.Count;
				try
				{
					this.jsonArrayContent = JArray.FromObject(this.groupFileItems).ToString();
					using (StreamWriter streamWriter = new StreamWriter(this.fileFullPath, false, Encoding.UTF8))
					{
						streamWriter.Write(this.jsonArrayContent);
						streamWriter.Flush();
					}
				}
				catch (Exception ex)
				{
					ILogNet logNet = this.LogNet;
					if (logNet != null)
					{
						logNet.WriteException("CacheJsonArrayContent", ex);
					}
				}
			}
			GroupFileContainer.FileCountChangedDelegate fileCountChanged = this.FileCountChanged;
			if (fileCountChanged != null)
			{
				fileCountChanged(this, this.filesCount);
			}
		}

		/// <summary>
		/// 从目录进行加载数据，必须实例化的时候加载，加载失败会导致系统异常，旧的文件丢失<br />
		/// Load data from the directory, it must be loaded when instantiating. Failure to load will cause system exceptions and old files will be lost
		/// </summary>
		/// <param name="path">当前的文件夹路径信息</param>
		// Token: 0x060019B1 RID: 6577 RVA: 0x00080DC8 File Offset: 0x0007EFC8
		private void LoadByPath(string path)
		{
			this.fileFolderPath = path;
			this.fileFullPath = Path.Combine(path, "list.txt");
			bool flag = !Directory.Exists(this.fileFolderPath);
			if (flag)
			{
				Directory.CreateDirectory(this.fileFolderPath);
			}
			bool flag2 = File.Exists(this.fileFullPath);
			if (flag2)
			{
				try
				{
					using (StreamReader streamReader = new StreamReader(this.fileFullPath, Encoding.UTF8))
					{
						this.groupFileItems = JArray.Parse(streamReader.ReadToEnd()).ToObject<List<GroupFileItem>>();
					}
				}
				catch (Exception ex)
				{
					ILogNet logNet = this.LogNet;
					if (logNet != null)
					{
						logNet.WriteException("GroupFileContainer", "Load files txt failed,", ex);
					}
				}
			}
			bool flag3 = this.groupFileItems == null;
			if (flag3)
			{
				this.groupFileItems = new List<GroupFileItem>();
			}
			this.coordinatorCacheJsonArray = new HslAsyncCoordinator(new Action(this.CacheJsonArrayContent));
			this.CacheJsonArrayContent();
		}

		/// <inheritdoc />
		// Token: 0x060019B2 RID: 6578 RVA: 0x00080ED0 File Offset: 0x0007F0D0
		public override string ToString()
		{
			return "GroupFileContainer[" + this.dirPath + "]";
		}

		// Token: 0x040005BB RID: 1467
		private string dirPath = string.Empty;

		// Token: 0x040005BC RID: 1468
		private const string FileListResources = "list.txt";

		// Token: 0x040005BD RID: 1469
		private ILogNet LogNet;

		// Token: 0x040005BE RID: 1470
		private string jsonArrayContent = "[]";

		// Token: 0x040005BF RID: 1471
		private int filesCount = 0;

		// Token: 0x040005C0 RID: 1472
		private object hybirdLock = new object();

		// Token: 0x040005C1 RID: 1473
		private HslAsyncCoordinator coordinatorCacheJsonArray;

		// Token: 0x040005C2 RID: 1474
		private List<GroupFileItem> groupFileItems;

		// Token: 0x040005C3 RID: 1475
		private string fileFolderPath;

		// Token: 0x040005C4 RID: 1476
		private string fileFullPath;

		/// <summary>
		/// 文件数量变化的委托信息
		/// </summary>
		/// <param name="container">文件列表容器</param>
		/// <param name="fileCount">文件的数量</param>
		// Token: 0x0200074B RID: 1867
		// (Invoke) Token: 0x06003188 RID: 12680
		public delegate void FileCountChangedDelegate(GroupFileContainer container, int fileCount);
	}
}
